package com.ywu.application.standard.fileSys.utils;

import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextApp;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.boot.exception.YwuRuntimeException;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.TimerIdGenerateUtil;
import com.ywu.application.standard.fileSys.config.YwuFileSysAppConfig;
import com.ywu.application.standard.fileSys.dto.YwuFileWhiteListDto;
import com.ywu.application.standard.fileSys.entity.YwuFileWhiteListEntity;
import com.ywu.application.standard.fileSys.service.YwuFileWhiteListService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName FileUtils
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/8/9 20:20
 * @Version 1.0
 **/
@Component
@Slf4j
public class FileUtils {
    @Autowired
    private YwuFileSysAppConfig ywuFileSysAppConfig;

    @Autowired
    private YwuFileWhiteListService ywuFileWhiteListService;

    /**
    * @Author GroundDemo
    * @Description 生成文件上传路径
    * @Date 20:24 2024/8/9
    * @Param []
    * @return java.lang.String
    **/
    public String generateFileDir() {
        // 获取上下文中的AppId
        YwuContextApp ywuContextApp = YwuContextHolder.getCurrentContext().getYwuContextApp();
        String appId = ywuContextApp.getAppId();
        String pathDir = ywuFileSysAppConfig.getFileRootDir() + File.separator + appId;
        // 如果文件夹不存在，则创建文件夹
        File file = new File(pathDir);
        if (!file.exists()) {
            boolean mkdirRes = file.mkdirs();
            if (!mkdirRes) {
                log.error("generateFileDir mkdir error, path is {}", pathDir);
                throw new YwuRuntimeException("generateFileDir mkdir error");
            }
        }
        return pathDir;
    }

    /**
    * @Author GroundDemo
    * @Description 获取文件名中的文件类型
    * @Date 20:32 2024/8/9
    * @Param [fileName]
    * @return java.lang.String
    **/
    public String getFileType(String fileName) {
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
        // 校验文件类型的合法性
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        String appId = currentContext.getYwuContextApp().getAppId();
        YwuFileWhiteListDto searchDto = new YwuFileWhiteListDto();
        searchDto.setAppId(appId);
        CommonResult<List<YwuFileWhiteListEntity>> searchRes = ywuFileWhiteListService.queryWhiteListByAppId(searchDto);
        if (Objects.isNull(searchRes) || !searchRes.getCode().equals("200")) {
            log.error("getFileType search file type is error {}", appId);
            throw new YwuRuntimeException("getFileType search file type is error");
        }
        List<YwuFileWhiteListEntity> data = searchRes.getData();
        if (CollectionUtils.isEmpty(data)) {
            log.error("getFileType res data is empty, file type is invalid {}", fileType);
            throw new YwuRuntimeException("getFileType res data is empty, file type is invalid");
        }
        Set<String> fileTypeWhiteSet = data.stream().map(YwuFileWhiteListEntity::getFileSuffix).collect(Collectors.toSet());
        if (!fileTypeWhiteSet.contains(fileType)) {
            log.error("getFileType file type is invalid {}", fileType);
            throw new YwuRuntimeException("getFileType file type is invalid");
        }
        return fileType;
    }

    /**
    * @Author GroundDemo
    * @Description 获取文件的具体名称
    * @Date 9:56 2024/8/10
    * @Param [fileName]
    * @return java.lang.String
    **/
    public String getFileName(String fileName) {
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
    * @Author GroundDemo
    * @Description 写入文件
    * @Date 20:49 2024/8/9
    * @Param [file, filePath]
    * @return void
    **/
    public void writeMultipartFile(MultipartFile file, String filePath) {
        File destFile = new File(filePath);
        log.debug("writeMultipartFile filePath is {}", filePath);
        try (InputStream is = file.getInputStream();
             OutputStream os = new FileOutputStream(destFile)) {
            byte[] buffer = new byte[1024];
            int readIndex = 0;
            while ((readIndex = is.read(buffer)) != -1) {
                os.write(buffer, 0, readIndex);
            }
        } catch (IOException e) {
            log.error("writeMultipartFile io exception {}", e.getMessage());
            throw new YwuRuntimeException("writeMultipartFile io exception");
        }
    }

    /**
    * @Author GroundDemo
    * @Description 拷贝文件
    * @Date 12:29 2024/9/16
    * @Param [sourceFilePath, destFilePath]
    * @return void
    **/
    public void copyFile(String sourceFilePath, String destFilePath, boolean isAppend) {
        File sourceFile = new File(sourceFilePath);
        File destFile = new File(destFilePath);
        try (InputStream is = new FileInputStream(sourceFile);
             OutputStream os = new FileOutputStream(destFile, isAppend)) {
            byte[] buffer = new byte[1024];
            int readIndex = 0;
            while ((readIndex = is.read(buffer)) != -1) {
                os.write(buffer, 0, readIndex);
            }
            os.flush();
        } catch (IOException e) {
            log.error("copyFile io exception {}", e.getMessage());
            throw new YwuRuntimeException("copyFile io exception");
        }
    }

    /**
    * @Author GroundDemo
    * @Description 删除文件
    * @Date 21:35 2024/8/9
    * @Param [filePath]
    * @return void
    **/
    public void deleteFile(String filePath) {
        File file = new File(filePath);
        boolean delete = file.delete();
        if (!delete) {
            log.warn("deleteFile failed {}", filePath);
        }
    }

    /**
    * @Author GroundDemo
    * @Description 重命名文件
    * @Date 21:40 2024/8/9
    * @Param [filePath]
    * @return String
    **/
    public String renameRandomTo(String filePath) {
        // 获取随机ID作为后缀
        String renameId = TimerIdGenerateUtil.nextId();
        File file = new File(filePath);
        String destFilePath = filePath + "_" + renameId;
        File destFile = new File(destFilePath);
        boolean res = file.renameTo(destFile);
        if (!res) {
            log.warn("renameRandomTo failed {}", destFilePath);
        }
        return destFilePath;
    }

    /**
    * @Author GroundDemo
    * @Description 重命名文件
    * @Date 22:00 2024/8/9
    * @Param [sourceFilePath, destFilePath]
    * @return boolean
    **/
    public void renameTo(String sourceFilePath, String destFilePath) {
        File sourceFile = new File(sourceFilePath);
        File destFile = new File(destFilePath);
        boolean res = sourceFile.renameTo(destFile);
        if (!res) {
            log.warn("renameTo failed {} {}", sourceFilePath, destFilePath);
        }
    }

    /**
    * @Author GroundDemo
    * @Description 查询文件类型后缀名称
    * @Date 8:58 2024/8/17
    * @Param []
    * @return java.util.Map<java.lang.String,java.lang.String>
    **/
    public Map<String, String> getFileTypeName() {
        Map<String, String> resMap = new HashMap<>();
        YwuFileWhiteListDto searchDto = new YwuFileWhiteListDto();
        searchDto.setAppId(YwuContextHolder.getCurrentContext().getYwuContextApp().getAppId());
        CommonResult<List<YwuFileWhiteListEntity>> result = ywuFileWhiteListService.queryWhiteListByAppId(searchDto);
        if (Objects.isNull(result) || !result.getCode().equals("200")) {
            return resMap;
        }
        List<YwuFileWhiteListEntity> data = result.getData();
        if (CollectionUtils.isEmpty(data)) {
            return resMap;
        }
        resMap = data.stream().collect(Collectors.toMap(YwuFileWhiteListEntity::getFileSuffix, YwuFileWhiteListEntity::getSuffixName, (v1, v2) -> v1));
        return resMap;
    }
}
